Skip to content

Fix clone() to update parent references on cloned children#443

Merged
MaxGhenis merged 2 commits intoPolicyEngine:masterfrom
MaxGhenis:fix-clone-parent-refs
Mar 10, 2026
Merged

Fix clone() to update parent references on cloned children#443
MaxGhenis merged 2 commits intoPolicyEngine:masterfrom
MaxGhenis:fix-clone-parent-refs

Conversation

@MaxGhenis
Copy link
Contributor

Summary

  • Fix ParameterNode.clone() to set child.parent = clone after cloning children
  • Fix ParameterScale.clone() to set bracket.parent = clone after cloning brackets
  • Add tests for parent references and cache invalidation after clone + update

After cloning, each child's parent still pointed to the original tree. This meant parameter.update() called clear_parent_cache() on the original parent instead of the clone, leaving stale cached values in the cloned tree.

This is the root cause of silent null returns for NJ reform calculations on the API, where clone() + parameter.update() is used instead of Reform.from_dict().

Fixes #442

Test plan

  • test_clone_parent_references — verifies cloned children reference the cloned parent
  • test_clone_scale_parent_references — verifies cloned scale brackets reference the cloned scale
  • test_clone_update_invalidates_cloned_cache — verifies parameter.update() on a cloned tree invalidates the clone's cache (not the original's)

🤖 Generated with Claude Code

MaxGhenis and others added 2 commits March 10, 2026 08:42
After cloning a ParameterNode, each child's `parent` still pointed
to the original tree. This meant parameter.update() called
clear_parent_cache() on the original parent, not the clone,
leaving stale cached values in the cloned tree.

This caused silent null returns for NJ reform calculations on the
API, where clone() + parameter.update() is used instead of
Reform.from_dict().

Fixes PolicyEngine#442

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
clear_parent_cache only cleared self._at_instant_cache inside the
`if self.parent is not None` block, so root nodes (parent=None)
never had their cache cleared. Move the clear() before the
conditional so all nodes in the chain are invalidated.

Confirmed: test_clone_update_invalidates_cloned_cache fails without
this fix and passes with it.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@MaxGhenis MaxGhenis force-pushed the fix-clone-parent-refs branch from 30e2c4f to d6d691b Compare March 10, 2026 12:43
@codecov
Copy link

codecov bot commented Mar 10, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 82.92%. Comparing base (8483579) to head (d6d691b).
⚠️ Report is 4 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #443      +/-   ##
==========================================
+ Coverage   82.51%   82.92%   +0.40%     
==========================================
  Files         202      202              
  Lines       10634    10660      +26     
  Branches     1069     1071       +2     
==========================================
+ Hits         8775     8840      +65     
+ Misses       1583     1536      -47     
- Partials      276      284       +8     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@MaxGhenis MaxGhenis merged commit f858858 into PolicyEngine:master Mar 10, 2026
18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

clone() + parameter.update() breaks ParameterNodeAtInstant iteration

1 participant